package org.example.es;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 文档高级查询
 */
public class ESDocAdvancedQueryDemo {
    public static void main(String[] args) throws IOException {
//        getAllDoc();
//        queryConditionDoc();
//        getPage();
//        sortDoc();
//        combinationQuery();
//        rangeQuery();
//        fuzzyQuery();
//        maxValueQuery();
        groupQueryDoc();
    }

    /**
     * 查询所有数据 默认10条
     */
    public static void getAllDoc() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);
                // 构建查询的请求体
                SearchSourceBuilder builder = new SearchSourceBuilder();
                // 查询所有数据  默认10条
                builder.query(QueryBuilders.matchAllQuery());
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 条件查询
     */
    public static void queryConditionDoc() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                // 创建搜索对象
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);
                // 构建查询的请求体
                SearchSourceBuilder builder = new SearchSourceBuilder();
                builder.query(QueryBuilders.termQuery("age", "2"))
//                        .query(QueryBuilders.termQuery("sex", "女"))  会覆盖上面的查询
                ;
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 分页查询
     */
    public static void getPage() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                // 创建搜索对象
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);
                // 构建查询的请求体
                SearchSourceBuilder builder = new SearchSourceBuilder();
                builder.query(QueryBuilders.matchAllQuery());
                // 分页查询
                // 当前页索引（第一条数据的顺序号）
                builder.from(0);// 0 代表第1页
                builder.size(20);// 每页显示多少条
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");

            }
        }.execute();
    }

    /**
     * 查询排序
     */
    public static void sortDoc() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);
                SearchSourceBuilder builder = new SearchSourceBuilder();
                builder.query(QueryBuilders.matchAllQuery());
                builder.sort("age", SortOrder.ASC);
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 组合查询
     */
    public static void combinationQuery() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);
                // 构建查询的请求体
                SearchSourceBuilder builder = new SearchSourceBuilder();
                BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
                // 必须包含
                boolQueryBuilder.must(QueryBuilders.matchQuery("age", 2));
                // 一定不含
                boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name", "能衤"));
                // 可能包含
                boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "女"));
//                builder.from(0);
//                builder.size(1000);
                builder.query(boolQueryBuilder);
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 范围查询
     */
    public static void rangeQuery() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);

                SearchSourceBuilder builder = new SearchSourceBuilder();
                RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("age");
                // 大于等于
//                rangeQueryBuilder.gte("15");
                // 小于等于
                rangeQueryBuilder.lte("20");
                builder.query(rangeQueryBuilder);// 默认10条
                builder.from(0);
                builder.size(100);
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 模糊查询
     */
    public static void fuzzyQuery() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest();
                request.indices(userIndex);
                SearchSourceBuilder builder = new SearchSourceBuilder();
                builder.query(QueryBuilders.fuzzyQuery("name", "明").fuzziness(Fuzziness.ONE));
                builder.from(0);
                builder.size(100);
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println("took:" + response.getTook());
                System.out.println("timeout:" + response.isTimedOut());
                System.out.println("total:" + hits.getTotalHits());
                System.out.println("MaxScore:" + hits.getMaxScore());
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 最大值查询
     */
    public static void maxValueQuery() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest().indices(userIndex);
                SearchSourceBuilder builder = new SearchSourceBuilder().aggregation(
                        AggregationBuilders.max("maxAge").field("age"));
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                SearchHits hits = response.getHits();
                System.out.println(response);
                System.out.println("hits========>>");
                for (SearchHit hit : hits) {
                    //输出每条查询的结果信息
                    System.out.println(hit.getSourceAsString());
                }
                System.out.println("<<========");
            }
        }.execute();
    }

    /**
     * 分组查询
     */
    public static void groupQueryDoc() throws IOException {
        new ElasticSearchTask() {
            @Override
            void doSomething(RestHighLevelClient client) throws IOException {
                SearchRequest request = new SearchRequest().indices(userIndex);
                SearchSourceBuilder builder = new SearchSourceBuilder();
                builder.aggregation(AggregationBuilders.terms("age_groupBy").field("age"));
                request.source(builder);
                SearchResponse response = client.search(request, RequestOptions.DEFAULT);
                // 查询匹配
                System.out.println(response);
                SearchHits hits = response.getHits();
                Map<String, Aggregation> aggregationMap = response.getAggregations().getAsMap();
                for (Map.Entry<String, Aggregation> entry : aggregationMap.entrySet()) {
                    System.out.printf("分组 %s 开始========%n", entry.getKey());
                    ParsedLongTerms terms = (ParsedLongTerms) entry.getValue();
                    List<? extends Terms.Bucket> buckets = terms.getBuckets();
                    for (Terms.Bucket bucket : buckets) {
                        System.out.println(bucket.getKeyAsString()+":"+bucket.getDocCount());
                    }
                    System.out.printf("分组 %s 结束========%n", entry.getKey());
                }
            }
        }.execute();
    }
}
